/**
 * Copyright (c) <2010>, <SUNNY GUPTA>
 * All rights reserved.

 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *   * Neither the name of the <ORGANIZATION> nor the
 *     names of its contributors may be used to endorse or promote products
 *     derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL <SUNNY GUPTA> BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package com.gwtp.investmentadvisor.server.authentication.actionhandler;

import java.util.logging.Level;
import java.util.logging.Logger;

import javax.persistence.EntityExistsException;

import com.google.inject.Inject;
import com.gwtp.investmentadvisor.server.authentication.AuthenticationManager;
import com.gwtp.investmentadvisor.server.authentication.entities.UserAccount;
import com.gwtp.investmentadvisor.server.core.security.CryptographyHelper;
import com.gwtp.investmentadvisor.shared.action.NewUserSignUpAttempt;
import com.gwtp.investmentadvisor.shared.action.NewUserSignUpAttemptResult;
import com.gwtp.investmentadvisor.shared.entities.NewUserInfo;
import com.gwtp.investmentadvisor.shared.entities.SignUpAttempResult;
import com.gwtp.investmentadvisor.shared.entities.UserRole;
import com.gwtp.investmentadvisor.shared.enums.NewUserSignUpFailureReason;
import com.gwtplatform.dispatch.server.ExecutionContext;
import com.gwtplatform.dispatch.server.actionhandler.ActionHandler;
import com.gwtplatform.dispatch.shared.ActionException;

/**
 * 
 * @author Sunny Gupta
 *
 */
public class NewUserSignUpAttemptHandler 
    implements ActionHandler<NewUserSignUpAttempt, NewUserSignUpAttemptResult> {
  
  private final AuthenticationManager authenticationManager;
  
  private static final String FAILURE_MESSAGE = "New User Sign Up failed";
  
  private static final Logger logger = Logger.getLogger(NewUserSignUpAttemptHandler.class.getName());

  @Inject
  public NewUserSignUpAttemptHandler(final AuthenticationManager authenticationManager) {
    this.authenticationManager = authenticationManager;
  }
  
  @Override
  public NewUserSignUpAttemptResult execute(NewUserSignUpAttempt action,
      ExecutionContext context) throws ActionException {
        
    // First check if username available
    NewUserInfo info = action.getNewUserInfo();
    
    boolean isSignedUp = false;
    NewUserSignUpFailureReason reason = null;
    
    String email = info.getEmail();
    
    // Attempt to add new
    try {
      // Generate password hash
      String passwordHash = CryptographyHelper.generateHash(info.getPassword());
      // Try add new user
      UserAccount newUser = new UserAccount(email, passwordHash);
      newUser.getUserRoles().add(UserRole.USER);
      authenticationManager.addNewUser(newUser);
      
      // Addition success
      isSignedUp = true;
    } catch (EntityExistsException e) {
      // Username already taken up
      reason = NewUserSignUpFailureReason.USERNAME_ALREADY_REGISTERED;
    } catch (Exception e) {
      // Log error
      logger.log(Level.SEVERE, FAILURE_MESSAGE, e);
      
      // Throw exception
      throw new ActionException(e);
    }
    
    // Form result
    NewUserSignUpAttemptResult result  = new NewUserSignUpAttemptResult(
        info, new SignUpAttempResult(isSignedUp, reason));
    
    return result;
  }

  @Override
  public Class<NewUserSignUpAttempt> getActionType() {
    return NewUserSignUpAttempt.class;
  }

  @Override
  public void undo(NewUserSignUpAttempt action,
      NewUserSignUpAttemptResult result, ExecutionContext context)
      throws ActionException {
    // TODO Auto-generated method stub
  }

}
